import 'package:dio/dio.dart';
import 'package:dio/dio.dart' as d;
import 'package:get/get.dart';
import '../config/api_config.dart';
import '../services/storage_service.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

class DioClient {
  static final DioClient _instance = DioClient._internal();
  late final Dio dio;

  factory DioClient() => _instance;

  // 取消请求token
  final CancelToken _cancelToken = CancelToken();

  DioClient._internal() {
    dio = Dio(BaseOptions(
      baseUrl: ApiConfig.baseUrl,
      connectTimeout: ApiConfig.connectTimeout,
      receiveTimeout: ApiConfig.receiveTimeout,
      headers: {'Content-Type': 'application/json'},
    ));

    dio.interceptors.addAll([
      _AuthInterceptor(),
      PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        responseBody: true,
        error: true,
      ),
    ]);
  }

  /// 取消网络请求
  void cancel([CancelToken? token]) {
    if (token != null) {
      token.cancel('cancel');
    } else {
      _cancelToken.cancel('cancel');
    }
  }

  Future<d.Response<T>> request<T>({
    required String path,
    String method = 'GET',
    Map<String, dynamic>? queryParameters,
    dynamic data,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    try {
      // 如果是表单上传，强制使用 multipart/form-data，避免全局 application/json 头覆盖
      final Options resolvedOptions = options ?? Options(method: method);
      if (data is d.FormData) {
        resolvedOptions.contentType = 'multipart/form-data';
      }
      final response = await dio.request<T>(
        path,
        queryParameters: queryParameters,
        data: data,
        options: resolvedOptions,
        cancelToken: cancelToken ?? _cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
      return response;
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Exception _handleError(DioException error) {
    switch (error.type) {
      case DioExceptionType.connectionTimeout:
        return Exception('Connection timeout');
      case DioExceptionType.receiveTimeout:
        return Exception('Receive timeout');
      case DioExceptionType.badResponse:
        final statusCode = error.response?.statusCode;
        final data = error.response?.data;
        if (data != null && data['msg'] != null) {
          return Exception(data['msg']);
        }
        return Exception('Error $statusCode: Something went wrong');
      default:
        return Exception('Network error occurred');
    }
  }
}

class _AuthInterceptor extends Interceptor {
  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    final token = Get.find<StorageService>().getToken();
    if (token != null) {
      // options.headers['Authorization'] = 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImYxNjk2NmUxLWNlN2YtNDJlOS05Yjc0LWRlODdmYTM4YWM2OSJ9.Pm1AfVHgxlV4y181b8wqC4IgxjljKHTgx6dYdzRkfYkY3vFRBy4MpHzftLHrL-AcYkQW6WnTMTq2g9D8qVyw-A';
      options.headers['Authorization'] = 'Bearer $token';
    }
    options.queryParameters['lang'] = Get.locale?.languageCode ?? 'zh';
    handler.next(options);
  }

  @override
  void onResponse(d.Response response, ResponseInterceptorHandler handler) {
    // 只有当 response.data 是 Map 时才检查 code
    if (response.data is Map && response.data['code'] == 401) {
      Get.find<StorageService>().clearToken();
      Get.offAllNamed('/login');
    }
    super.onResponse(response, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    if (err.response?.statusCode == 401) {
      Get.find<StorageService>().clearToken();
      Get.offAllNamed('/login');
    }
    handler.next(err);
  }
}
